package com.epam.Bank;

import java.util.Random;

import org.apache.log4j.Logger;

import com.epam.Bank.Bank.Currency;
import com.epam.Client.Client;

public class Cashier {

	private int cashierCashUSD;
	private int cashierCashEuro;

	Random rand = new Random(2000);
	public static Logger log = Logger.getLogger(Cashier.class);

	public Cashier() throws InterruptedException {
		cashierCashUSD = rand.nextInt(1000);
		cashierCashEuro = rand.nextInt(1000);
		Bank.setCashier(this);
	}

	public Cashier(int initialCashUSD, int initialCashEuro)
			throws InterruptedException {
		cashierCashUSD = initialCashUSD;
		setCashierCashEuro(initialCashEuro);
		Bank.setCashier(this);
	}

	public synchronized void checkCashierCash(Currency currency, int amount) {
		switch (currency) {
		case USD:
			if (this.getCashierCashUSD() < amount) {
				Bank.setStorageUSD(Bank.getStorageUSD()
						+ this.getCashierCashUSD() - amount);
				this.setCashierCashUSD(amount);
			}
			break;
		case Euro:
			if (this.getCashierCashEuro() < amount) {
				Bank.setStorageEuro(Bank.getStorageEuro()
						+ this.getCashierCashEuro() - amount);
				this.setCashierCashEuro(amount);
			}
			break;
		}
	}

	public void deposit(Client c, Currency currency, int amount)
			throws NullPointerException {
		int i;
		switch (currency) {
		case USD:
			if (amount <= c.getClientCashUSD()) {
				i = Bank.getAccountMap().get(c.getAccountNumber())
						.getAccountBalanceUSD()
						+ amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceUSD(i);
				this.cashierCashUSD += amount;
				log.info("Client deposited " + amount + " " + currency);
				break;
			} else {
				log.info("Client has not enough cash");
			}
		case Euro:
			if (amount <= c.getClientCashEuro()) {
				i = Bank.getAccountMap().get(c.getAccountNumber())
						.getAccountBalanceEuro()
						+ amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceEuro(i);
				this.cashierCashEuro += amount;
				log.info("Client deposited " + amount + " " + currency);
				break;
			} else {
				log.info("Client has not enough cash");
			}

		}
	}

	public void exchange(Client c, Currency sourceCurrency,
			Currency destinationCurrency, int amount) {
		switch (sourceCurrency) {
		case Euro:
			if (amount <= c.getClientCashEuro()) {
				checkCashierCash(Currency.USD,
						(int) ((int) amount * Bank.getEuroToUSDRate()));
				c.setClientCashEuro(c.getClientCashEuro() - amount);
				this.setCashierCashEuro(this.getCashierCashEuro() + amount);
				this.setCashierCashUSD((int) (this.getCashierCashUSD() - amount
						* Bank.getEuroToUSDRate()));
				c.setClientCashUSD((int) (amount * Bank.getEuroToUSDRate()));
				log.info("Client exchanged " + amount +  " " + sourceCurrency
						+ " for " + amount * Bank.getEuroToUSDRate()
						+  " " + destinationCurrency);
				break;
			}
		case USD:
			if (amount <= c.getClientCashUSD()) {
				checkCashierCash(Currency.Euro,
						(int) ((int) amount * Bank.getUSDToEuroRate()));
				c.setClientCashUSD(c.getClientCashUSD() - amount);
				this.setCashierCashUSD(this.getCashierCashUSD() + amount);
				this.setCashierCashEuro((int) (this.getCashierCashEuro() - amount
						* Bank.getUSDToEuroRate()));
				c.setClientCashEuro((int) (amount * Bank.getUSDToEuroRate()));
				log.info("Client exchanged " + amount +  " " + sourceCurrency
						+ " for " + amount * Bank.getUSDToEuroRate()
						+  " " + destinationCurrency);
				break;

			}
		}
	}

	public int getCashierCashEuro() {
		return cashierCashEuro;
	}

	public int getCashierCashUSD() {
		return cashierCashUSD;
	}

	public void setCashierCashEuro(int cashierCashEuro) {
		this.cashierCashEuro = cashierCashEuro;
	}

	public void setCashierCashUSD(int cashierCash) {
		this.cashierCashUSD = cashierCash;
	}

	public void transfer(Client c, Client d, Currency currency, int amount) {
		int i;
		switch (currency) {
		case USD:
			if (c.getAccountBalanceUSD() >= amount) {
				i = c.getAccountBalanceUSD() - amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceUSD(i);
				i = d.getAccountBalanceUSD() + amount;
				Bank.getAccountMap().get(d.getAccountNumber())
						.setAccountBalanceUSD(i);
				;
				break;
			}
		case Euro:
			if (c.getAccountBalanceEuro() >= amount) {
				i = c.getAccountBalanceEuro() - amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceEuro(i);
				i = d.getAccountBalanceEuro() + amount;
				Bank.getAccountMap().get(d.getAccountNumber())
						.setAccountBalanceEuro(i);
				break;
			}
		}
	}

	public void withdraw(Client c, Currency currency, int amount) {
		int i;
		switch (currency) {
		case USD:
			if (amount <= Bank.getAccountMap().get(c.getAccountNumber())
					.getAccountBalanceUSD()) {
				checkCashierCash(currency, amount);
				i = Bank.getAccountMap().get(c.getAccountNumber())
						.getAccountBalanceUSD()
						- amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceUSD(i);
				c.setClientCashUSD(amount);
				this.cashierCashUSD -= amount;
				break;
			}
		case Euro:
			if (amount <= Bank.getAccountMap().get(c.getAccountNumber())
					.getAccountBalanceEuro()) {
				checkCashierCash(currency, amount);
				i = Bank.getAccountMap().get(c.getAccountNumber())
						.getAccountBalanceEuro()
						- amount;
				Bank.getAccountMap().get(c.getAccountNumber())
						.setAccountBalanceEuro(i);
				c.setClientCashEuro(amount);
				this.cashierCashEuro -= amount;
				break;
			}
		}
	}

}
